package cn.tedu.search.repository;

import cn.tedu.search.entity.Item;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

// Repository这个单词对Spring家族持久层包名、类名、接口名的命名规范
@Repository
public interface ItemRepository extends ElasticsearchRepository<Item, Long> {
    // ItemRepository接口要继承SpringData提供的父接口ElasticsearchRepository
    // ElasticsearchRepository接口后面跟的泛型焊锡<[实体类类型], [实体键主键类型]>
    // 一旦继承，当前接口就可以使用父接口中定义的方法来连接\操作ES了
    // 继承效果就是当前接口直接自动生成对指定实体类类型对应索引的基本增删改查方法
    // 因为当前指定的实体类泛型（Item）类中编写了对应索引名称，所以当前接口是可以找到指定索引的

    // SpringData自定义查询
    // 我们要编写的查询要遵循SpringData给定的格式，来定义一个方法名
    // SpringData会根据方法名自动推测出查询意图，生成能够完成查询的语句
    // query(查询)：表示当前方法是一个查询方法，类似sql语句汇总的select
    // Item/Items：表示要查询的实体类名称，返回的如果是集合需要在实体类名称后面加s
    // By(通过\根据)：表示开始设置查询的条件，等价于sql语句中的where
    // Title：设置要查询的字段，可以设置任何Item类中的任何字段
    // Matches(匹配)：表示支持查询的条件，matches是匹配字符串的关键字，
    // 如果字符串是支持分词的，就按照分词匹配，类似于sql语句中的like
    Iterable<Item> queryItemsByTitleMatches(String title);

    // 多条件自定义查询
    // 多个条件之间使用and或or来分隔，以表示多个条件间的逻辑运算关系
    // 下面我们使用title和brand字段进行多条件查询
    // 多个条件时，方法名会按照规则编写多个条件，参数也要根据条件的数量来变化
    // 声明参数时，要根据方法名中需要参数的次序声明对应的参数，参数对应规则和参数名称无关
    Iterable<Item> queryItemsByTitleMatchesAndBrandMatches(String title,
                                                           String brand);
    // 排序查询
    // 方法名称中添加OrderBy关键字，指定排序的字段和排序的方向
    Iterable<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
            String title, String brand);

    // 分页查询
    // 执行分页查询必须要指定查询的页码，和每页的条数
    // 这两个数据可以封装在Pageable类型的参数中，框架规定，这个参数必须放在参数列表中最后一个
    // 返回值方面：分页查询时，我们返回给前端的数据不但要包含查询到的当前页数据，还要包含分页信息
    // 分页信息指：当前页码，每页条数，总页数，总条数，有没有上一页\有没有下一页...等
    // 返回值修改为Page类型，就能满足这个条件
    Page<Item> queryItemsByTitleMatchesOrBrandMatchesOrderByPriceDesc(
            String title, String brand, Pageable pageable);
}
